#ifndef __ETCD_HPP__
#define __ETCD_HPP__
#include <etcd/Client.hpp>
#include <etcd/KeepAlive.hpp>
#include <etcd/Response.hpp>
#include <etcd/Value.hpp>
#include <etcd/Watcher.hpp>
#include "logger.hpp"
// 服务注册客户端类
class Registrant
{
public:
    Registrant(const std::string &host) : _client(std::make_shared<etcd::Client>(host)),
                                           _keep_alive(_client->leasekeepalive(3).get()),
                                           _lease_id(_keep_alive->Lease())
    {
    }
    ~Registrant()
    {
        _keep_alive->Cancel();
    }
    bool registery(const std::string &key, const std::string &value)
    {
        auto resp = _client->put(key.c_str(), value.c_str(), _lease_id).get();
        if (resp.is_ok() == false)
        {
            LOG_ERROR("注册数据失败:{}", resp.error_message());
            return false;
        }
        return true;
    }

private:
    std::shared_ptr<etcd::Client> _client;
    std::shared_ptr<etcd::KeepAlive> _keep_alive;
    uint64_t _lease_id;
};

// 服务发现客户端类
class Discoverer
{
    using NotifyCallback = std::function<void(std::string, std::string)>;

public:
    void callback(const etcd::Response &resp)
    {
        if (resp.is_ok() == false)
        {
            std::cout << "收到一个错误的事件通知：" << resp.error_message() << std::endl;
            return;
        }
        for (const auto &ev : resp.events())
        {
            if (ev.event_type() == etcd::Event::EventType::PUT)
            {
                if(_put_cb) _put_cb(ev.kv().key(),ev.kv().as_string());
                LOG_DEBUG("新增服务: {}-{}",ev.kv().key() , ev.kv().as_string());
            }
            else if (ev.event_type() == etcd::Event::EventType::DELETE_)
            {
                if(_del_cb) _del_cb(ev.prev_kv().key(),ev.prev_kv().as_string());
                LOG_DEBUG("下线服务: {}-{}",ev.prev_kv().key() , ev.prev_kv().as_string());
            }
        }
    }
    Discoverer(const std::string& host,
               const std::string &base_dir,
               const NotifyCallback &put_cb,
               const NotifyCallback &del_cb)
        : _client(std::make_shared<etcd::Client>(host)), _watcher(std::make_shared<etcd::Watcher>(*_client.get()
        , base_dir
        , std::bind(&Discoverer::callback, this, placeholders::_1), true))
        , _put_cb(put_cb), _del_cb(del_cb)

    {
        // 先进行服务发现，先获取到当前已有的数据
        auto resp = _client->ls("/service").get();
        if (resp.is_ok() == false)
        {
            LOG_ERROR("获取服务信息数据失败: {}", resp.error_message());
        }
        int sz = resp.keys().size();
        for (int i = 0; i < sz; ++i)
        {
            std::cout << resp.value(i).as_string() << "可以提供" << resp.key(i) << "服务" << std::endl;
            if (_put_cb)
            {
                _put_cb(resp.key(i), resp.value(i).as_string());
            }
        }
        _watcher = std::make_shared<etcd::Watcher>(*_client.get()
        , base_dir
        , std::bind(&Discoverer::callback, this, std::placeholders::_1)
        , true);
    }

private:
    std::shared_ptr<etcd::Client> _client;
    std::shared_ptr<etcd::Watcher> _watcher;
    NotifyCallback _put_cb;
    NotifyCallback _del_cb;
};
#endif